package cz.pproproj.aaservice.ddbmodule.dbaccess;

import cz.pproproj.aaservice.guimodule.model.AuthenticationException;
import cz.pproproj.aaservice.aasbllmodule.authentication.AuthenticationUser;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.List;

/**
 * Instance of this class could be accessed via {@link cz.pproproj.aaservice.ddbmodule.DataDBModuleImpl#getDbUsersManagement(String)}
 * This class is used to operations with users in DB
 * @author David
 * @since 11. 1. 2015
 */
@Transactional
public class DBUsersManagementImpl implements DBUsersManagement {

    @PersistenceContext
    private EntityManager em;

    DBUsersManagementImpl() {
    }

    @Override
    public String addUser(AuthenticationUser user) {
        DBUserDAO dbUser = new DBUserDAO(user.getUserName(), user.getPassword());
        em.persist(dbUser);
        return dbUser.getUserName();
    }

    @Override
    public List<AuthenticationUser> getAllUsers() {
        List<DBUserDAO> dbUsers = em.createQuery("SELECT u FROM DBUserDAO u", DBUserDAO.class).getResultList();
        return transformDbUsersToAuthorizationUsers(dbUsers);
    }

    private List<AuthenticationUser> transformDbUsersToAuthorizationUsers(List<DBUserDAO> dbUsers) {
        List<AuthenticationUser> users = new ArrayList<>();
        for (DBUserDAO user : dbUsers) {
            users.add(new AuthenticationUser(user.getUserName(), user.getPassword()));
        }
        return users;
    }

    @Override
    public boolean authenticate(AuthenticationUser user) throws AuthenticationException {
        List<DBUserDAO> users = em.createQuery("SELECT u FROM DBUserDAO u WHERE userName = :userName", DBUserDAO.class)
                .setParameter("userName", user.getUserName())
                .getResultList();
        if (users.size() > 1) {
            throw new AuthenticationException("There is multiple users with username: " + user.getUserName() + " in DB");
        }
        if (users.size() == 0) {
            return false;//non existing username
        }
        //todo there will be some hashing of password if it is not going to be in BLL for all modules same
        return users.get(0).getPassword().equals(user.getPassword());
    }

    private DBUserDAO getUserByUserName(String userName) throws AuthenticationException {
        List<DBUserDAO> users = em.createQuery("SELECT u FROM DBUserDAO u WHERE userName = :userName", DBUserDAO.class)
                .setParameter("userName", userName)
                .getResultList();
        if (users.size() > 1) {
            throw new AuthenticationException("There is multiple users with username: " + userName + " in DB");
        }
        if (users.size() == 0) {
            return null;//non existing username
        }
        return users.get(0);

    }

    @Override
    public void deleteUser(AuthenticationUser user) throws AuthenticationException {
        DBUserDAO dbUserDAO = getUserByUserName(user.getUserName());
        if (dbUserDAO == null) {
            throw new AuthenticationException("There is no user with username: " + user.getUserName() + " in DB");
        } else {
            em.remove(dbUserDAO);
        }

    }
}
